1   /*
2    * Copyright (C) 2011 The Guava Authors
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5    * in compliance with the License. You may obtain a copy of the License at
6    *
7    * http://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software distributed under the License
10   * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11   * or implied. See the License for the specific language governing permissions and limitations under
12   * the License.
13   */
14  
15  package com.google.common.cache;
16  
17  import static com.google.common.base.Preconditions.checkNotNull;
18  
19  import com.google.common.annotations.GwtCompatible;
20  import com.google.common.collect.Maps;
21  
22  import java.util.Map;
23  import java.util.concurrent.atomic.AtomicInteger;
24  
25  import javax.annotation.Nullable;
26  
27  /**
28   * Utility {@link CacheLoader} implementations intended for use in testing.
29   *
30   * @author mike nonemacher
31   */
32  @GwtCompatible(emulated = true)
33  class TestingCacheLoaders {
34  
35    /**
36     * Returns a {@link CacheLoader} that implements a naive {@link CacheLoader#loadAll}, delegating
37     * {@link CacheLoader#load} calls to {@code loader}.
38     */
39    static <K, V> CacheLoader<K, V> bulkLoader(final CacheLoader<K, V> loader) {
40      checkNotNull(loader);
41      return new CacheLoader<K, V>() {
42        @Override
43        public V load(K key) throws Exception {
44          return loader.load(key);
45        }
46  
47        @Override
48        public Map<K, V> loadAll(Iterable<? extends K> keys) throws Exception {
49          Map<K, V> result = Maps.newHashMap(); // allow nulls
50          for (K key : keys) {
51            result.put(key, load(key));
52          }
53          return result;
54        }
55      };
56    }
57  
58    /**
59     * Returns a {@link CacheLoader} that returns the given {@code constant} for every request.
60     */
61    static <K, V> ConstantLoader<K, V> constantLoader(@Nullable V constant) {
62      return new ConstantLoader<K, V>(constant);
63    }
64  
65    /**
66     * Returns a {@link CacheLoader} that returns the given {@code constant} for every request.
67     */
68    static IncrementingLoader incrementingLoader() {
69      return new IncrementingLoader();
70    }
71  
72    /**
73     * Returns a {@link CacheLoader} that throws the given error for every request.
74     */
75    static <K, V> CacheLoader<K, V> errorLoader(final Error e) {
76      checkNotNull(e);
77      return new CacheLoader<K, V>() {
78        @Override
79        public V load(K key) {
80          throw e;
81        }
82      };
83    }
84  
85    /**
86     * Returns a {@link CacheLoader} that throws the given exception for every request.
87     */
88    static <K, V> CacheLoader<K, V> exceptionLoader(final Exception e) {
89      checkNotNull(e);
90      return new CacheLoader<K, V>() {
91        @Override
92        public V load(K key) throws Exception {
93          throw e;
94        }
95      };
96    }
97  
98    /**
99     * Returns a {@link CacheLoader} that returns the key for every request.
100    */
101   static <T> IdentityLoader<T> identityLoader() {
102     return new IdentityLoader<T>();
103   }
104 
105   /**
106    * Returns a {@code new Object()} for every request, and increments a counter for every request.
107    * The count is accessible via {@link #getCount}.
108    */
109   static class CountingLoader extends CacheLoader<Object, Object> {
110     private final AtomicInteger count = new AtomicInteger();
111 
112     @Override
113     public Object load(Object from) {
114       count.incrementAndGet();
115       return new Object();
116     }
117 
118     public int getCount() {
119       return count.get();
120     }
121   }
122 
123   static final class ConstantLoader<K, V> extends CacheLoader<K, V> {
124     private final V constant;
125 
126     ConstantLoader(V constant) {
127       this.constant = constant;
128     }
129 
130     @Override
131     public V load(K key) {
132       return constant;
133     }
134   }
135 
136   /**
137    * Returns a {@code new Object()} for every request, and increments a counter for every request.
138    * An {@code Integer} loader that returns the key for {@code load} requests, and increments the
139    * old value on {@code reload} requests. The load counts are accessible via {@link #getLoadCount}
140    * and {@link #getReloadCount}.
141    */
142   static class IncrementingLoader extends CacheLoader<Integer, Integer> {
143     private final AtomicInteger countLoad = new AtomicInteger();
144     private final AtomicInteger countReload = new AtomicInteger();
145 
146     @Override
147     public Integer load(Integer key) {
148       countLoad.incrementAndGet();
149       return key;
150     }
151 
152     public int getLoadCount() {
153       return countLoad.get();
154     }
155 
156     public int getReloadCount() {
157       return countReload.get();
158     }
159   }
160 
161   static final class IdentityLoader<T> extends CacheLoader<T, T> {
162     @Override
163     public T load(T key) {
164       return key;
165     }
166   }
167 }
168